﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Windows;
using System.Windows.Media;

namespace VisualView.Axis
{
    /// <summary>
    /// 字符串轴
    /// </summary>
    public class StringAxis : BaseAxis<string>
    {
        /// <summary>
        /// 字符串集合
        /// </summary>
        public IList<string> Items
        {
            get { return (IList<string>)GetValue(ItemsProperty); }
            set { SetValue(ItemsProperty, value); }
        }
        public static readonly DependencyProperty ItemsProperty = DependencyProperty.Register("Items", typeof(IList<string>), typeof(StringAxis), new PropertyMetadata(RangeChangedNeedRefresh));

        public override AxisValueLocationConvertParam GetValueLocationParam()
        {
            return new StringAxisValueLocationConvertParam(Items.ToList(), GetLength(), AxisType);
        }

        /// <summary>
        /// 查询字符串中心位置
        /// </summary>
        /// <param name="str"></param>
        /// <returns></returns>
        public override double GetValueLocation(string str, AxisValueLocationConvertParam param)
        {
            if (param is StringAxisValueLocationConvertParam np)
            {
                if (np.Items == null || np.Items.Count <= 0) return np.Length / 2;
                var count = np.Items.Count;
                var itemlength = np.Length / count;
                var index = np.Items.IndexOf(str);
                var temp = index * itemlength + itemlength / 2;
                return (np.AxisType == AxisType.X || np.AxisType == AxisType.X2) ? temp : np.Length - temp;
            }
            else return default;
        }

        /// <summary>
        /// 获取指定位置的字符串
        /// </summary>
        /// <param name="location"></param>
        /// <returns></returns>
        public override string GetLocationValue(double location, AxisValueLocationConvertParam param)
        {
            if (param is StringAxisValueLocationConvertParam np)
            {
                if (np.Items == null || np.Items.Count <= 0) return string.Empty;
                var itemlength = np.Length / np.Items.Count;
                var index = Convert.ToInt32(Math.Floor(location / itemlength));
                if (index < 0 || index >= np.Items.Count) return string.Empty;
                return np.Items[(np.AxisType == AxisType.X || np.AxisType == AxisType.X2) ? index : np.Items.Count - index - 1];
            }
            else return string.Empty;
        }

        public override void Refresh()
        {
            if (!this.IsLoaded) return;
            var length = GetLength();
            using (var dc = Visual.RenderOpen())
            {
                dc.DrawRectangle(Background, null, new Rect(0, 0, this.ActualWidth, this.ActualHeight));
                DrawingAxisLine(dc);
                if (Items != null && Items.Count > 0)
                {
                    var count = Items.Count;
                    var itemlength = length / count;
                    for (int i = 0; i < count; i++)
                    {
                        var item = Items[i];
                        var sg = CreateTextGeometry(item, FontSize, out double width, out double height);
                        var location = itemlength * i + itemlength / 2;
                        if (AxisType == AxisType.X)
                        {
                            dc.DrawLine(LinePen, new Point(location, 0), new Point(location, 5));
                            sg.Transform = new MatrixTransform(1, 0, 0, 1, location - width / 2, 5);
                        }
                        else if (AxisType == AxisType.X2)
                        {
                            dc.DrawLine(LinePen, new Point(location, this.ActualHeight), new Point(location, this.ActualHeight - 5));
                            sg.Transform = new MatrixTransform(1, 0, 0, 1, location - width / 2, this.ActualHeight - height - 5);
                        }
                        else if (AxisType == AxisType.Y)
                        {
                            dc.DrawLine(LinePen, new Point(this.ActualWidth, location), new Point(this.ActualWidth - 5, location));
                            sg.Transform = new MatrixTransform(0, -1, 1, 0, this.ActualWidth - 5 - height, location + width / 2);
                        }
                        else
                        {
                            dc.DrawLine(LinePen, new Point(0, location), new Point(5, location));
                            sg.Transform = new MatrixTransform(0, 1, -1, 0, 5 + height, location - width / 2);
                        }
                        dc.DrawGeometry(TextPen.Brush, TextPen, sg);
                    }
                }
            }
        }
    }

    public class StringAxisValueLocationConvertParam : AxisValueLocationConvertParam
    {

        public List<string> Items { get; protected set; }

        public StringAxisValueLocationConvertParam(List<string> items, double length, AxisType axisType) : base(length, axisType)
        {
            Items = items;
        }
    }
}
